/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package game.gamemath;

/**
 *
 * @author UtMan
 */
public class matrix3
{
    vec3 axis_x; float pad_xw;
    vec3 axis_y; float pad_yw;
    vec3 axis_z; float pad_zw;
    vec3 axis_w; float pad_ww;

    public matrix3()
    {
        axis_x = vec3.Zero();
        axis_y = vec3.Zero();
        axis_z = vec3.Zero();
        axis_w = vec3.Zero();
        pad_xw = 0.0f;
        pad_yw = 0.0f;
        pad_zw = 0.0f;
        pad_ww = 0.0f;
    }

    public matrix3(vec3 axisX, vec3 axisY, vec3 axisZ, vec3 axisW, vec4 padding)
    {
        axis_x = axisX;
        axis_y = axisY;
        axis_z = axisZ;
        axis_w = axisW;
        pad_xw = padding.X();
        pad_yw = padding.Y();
        pad_zw = padding.Z();
        pad_ww = padding.W();
    }

    public matrix3(float[] elm)
            throws ArrayIndexOutOfBoundsException
    {
        if(elm.length != 16)
            throw new ArrayIndexOutOfBoundsException("Incompatable array size for matrix3");
        axis_x = new vec3(elm[0],  elm[1],  elm[2]);  pad_xw = elm[3];
        axis_y = new vec3(elm[4],  elm[5],  elm[6]);  pad_yw = elm[7];
        axis_z = new vec3(elm[8],  elm[9],  elm[10]); pad_zw = elm[11];
        axis_w = new vec3(elm[12], elm[13], elm[14]); pad_ww = elm[15];

    }

    public static matrix3 Identity()
    {
        matrix3 ident = new matrix3();
        ident.axis_x = vec3.Right();
        ident.axis_y = vec3.Up();
        ident.axis_z = vec3.Forward();
        ident.axis_w = vec3.Zero();
        ident.pad_xw = ident.pad_yw = ident.pad_zw = 0;
        ident.pad_ww = 1;
        return ident;
    }

    public static matrix3 Zero()
    {
        return new matrix3();
    }

    public static matrix3 MakeTranslation(vec3 Trans)
    {
        vec4 translate =  new vec4(Trans.X(), Trans.Y(), Trans.Z(), 1.0f);
        return new matrix3(vec3.Right(), vec3.Up(), vec3.Forward(), vec3.Zero(), translate);
    }

    public static matrix3 MakeScale(vec3 Scale)
    {
        float[] scale = { Scale.X(), 0,0,0,
                          Scale.Y(), 0,0,0,
                          Scale.Z(), 0,0,0,
                          0,0,0,1 };
        return new matrix3(scale);
    }

    public static matrix3 MakeXRotation(float degrees)
    {
        float rad = (float)java.lang.Math.toRadians(degrees);
        float[] rot = { 0,0,0,0,
                        0,0,0,0,
                        0,0,0,0,
                        0,0,0,0 };
        
        return new matrix3(rot);
    }

    public static matrix3 MakeYRotation(float degrees)
    {
        float rad = (float)java.lang.Math.toRadians(degrees);
        float[] rot = { 0,0,0,0,
                        0,0,0,0,
                        0,0,0,0,
                        0,0,0,0 };
        
        return new matrix3(rot);
    }

    public static matrix3 MakeZRotation(float degrees)
    {
        float rad = (float)java.lang.Math.toRadians(degrees);
        float[] rot = { 0,0,0,0,
                        0,0,0,0,
                        0,0,0,0,
                        0,0,0,0 };
        
        return new matrix3(rot);
    }

    public vec3 GetPosition()
    {
        return new vec3(pad_xw, pad_yw, pad_zw);
    }

    public vec3 GetForward()
    {

    }

    public vec3 GetUp()
    {

    }

    public vec3 GetRight()
    {

    }

    public matrix3 Plus(matrix3 rhs)
    {
        
    }

    public matrix3 Minus(matrix3 rhs)
    {

    }

    public matrix3 MultipliedBy(matrix3 rhs)
    {
        matrix3 ret = new matrix3();
        //Mult._e11=m._e11*n._e11+m._e12*n._e21+m._e13*n._e31+m._e14*n._e41;
	//Mult._e12=m._e11*n._e12+m._e12*n._e22+m._e13*n._e32+m._e14*n._e42;
	//Mult._e13=m._e11*n._e13+m._e12*n._e23+m._e13*n._e33+m._e14*n._e43;
	//Mult._e14=m._e11*n._e14+m._e12*n._e24+m._e13*n._e34+m._e14*n._e44;
	//Mult._e21=m._e21*n._e11+m._e22*n._e21+m._e23*n._e31+m._e24*n._e41;
	//Mult._e22=m._e21*n._e12+m._e22*n._e22+m._e23*n._e32+m._e24*n._e42;
	//Mult._e23=m._e21*n._e13+m._e22*n._e23+m._e23*n._e33+m._e24*n._e43;
	//Mult._e24=m._e21*n._e14+m._e22*n._e24+m._e23*n._e34+m._e24*n._e44;
	//Mult._e31=m._e31*n._e11+m._e32*n._e21+m._e33*n._e31+m._e34*n._e41;
	//Mult._e32=m._e31*n._e12+m._e32*n._e22+m._e33*n._e32+m._e34*n._e42;
	//Mult._e33=m._e31*n._e13+m._e32*n._e23+m._e33*n._e33+m._e34*n._e43;
	//Mult._e34=m._e31*n._e14+m._e32*n._e24+m._e33*n._e34+m._e34*n._e44;
	//Mult._e41=m._e41*n._e11+m._e42*n._e21+m._e43*n._e31+m._e44*n._e41;
	//Mult._e42=m._e41*n._e12+m._e42*n._e22+m._e43*n._e32+m._e44*n._e42;
	//Mult._e43=m._e41*n._e13+m._e42*n._e23+m._e43*n._e33+m._e44*n._e43;
	//Mult._e44=m._e41*n._e14+m._e42*n._e24+m._e43*n._e34+m._e44*n._e44;
        
        ret.axis_x.X(  this.axis_x.X()*rhs.axis_x.X() +
                       this.axis_x.Y()*rhs.axis_y.X() +
                       this.axis_x.Z()*rhs.axis_z.X() +
                       this.pad_xw    *rhs.axis_w.X());
        ret.axis_x.Y(  this.axis_x.X()*rhs.axis_x.Y() +
                       this.axis_x.Y()*rhs.axis_y.Y() +
                       this.axis_x.Z()*rhs.axis_z.Y() +
                       this.pad_xw    *rhs.axis_w.Y());
        ret.axis_x.Z(  this.axis_x.X()*rhs.axis_x.Z() +
                       this.axis_x.Y()*rhs.axis_y.Z() +
                       this.axis_x.Z()*rhs.axis_z.Z() +
                       this.pad_xw    *rhs.axis_w.Z());
        ret.pad_xw =   this.axis_x.X()*rhs.pad_xw     +
                       this.axis_x.Y()*rhs.pad_yw     +
                       this.axis_x.Z()*rhs.pad_zw     +
                       this.pad_xw    *rhs.pad_ww     ;

        ret.axis_y.X(  this.axis_y.X()*rhs.axis_x.X() +
                       this.axis_y.Y()*rhs.axis_y.X() +
                       this.axis_y.Z()*rhs.axis_z.X() +
                       this.pad_yw    *rhs.axis_w.X());
        ret.axis_y.Y(  this.axis_y.X()*rhs.axis_x.Y() +
                       this.axis_y.Y()*rhs.axis_y.Y() +
                       this.axis_y.Z()*rhs.axis_z.Y() +
                       this.pad_yw    *rhs.axis_w.Y());
        ret.axis_y.Z(  this.axis_y.X()*rhs.axis_x.Z() +
                       this.axis_y.Y()*rhs.axis_y.Z() +
                       this.axis_y.Z()*rhs.axis_z.Z() +
                       this.pad_yw    *rhs.axis_w.Z());
        ret.pad_yw =   this.axis_y.X()*rhs.pad_xw     +
                       this.axis_y.Y()*rhs.pad_yw     +
                       this.axis_y.Z()*rhs.pad_zw     +
                       this.pad_yw    *rhs.pad_ww     ;
        
        ret.axis_z.X(  this.axis_z.X()*rhs.axis_x.X() +
                       this.axis_z.Y()*rhs.axis_y.X() +
                       this.axis_z.Z()*rhs.axis_z.X() +
                       this.pad_zw    *rhs.axis_w.X());
        ret.axis_z.Y(  this.axis_z.X()*rhs.axis_x.Y() +
                       this.axis_z.Y()*rhs.axis_y.Y() +
                       this.axis_z.Z()*rhs.axis_z.Y() +
                       this.pad_zw    *rhs.axis_w.Y());
        ret.axis_z.Z(  this.axis_z.X()*rhs.axis_x.Z() +
                       this.axis_z.Y()*rhs.axis_y.Z() +
                       this.axis_z.Z()*rhs.axis_z.Z() +
                       this.pad_zw    *rhs.axis_w.Z());
        ret.pad_zw =   this.axis_z.X()*rhs.pad_xw     +
                       this.axis_z.Y()*rhs.pad_yw     +
                       this.axis_z.Z()*rhs.pad_zw     +
                       this.pad_zw    *rhs.pad_ww     ;

        ret.axis_w.X(  this.axis_w.X()*rhs.axis_x.X() +
                       this.axis_w.Y()*rhs.axis_y.X() +
                       this.axis_w.Z()*rhs.axis_z.X() +
                       this.pad_ww    *rhs.axis_w.X());
        ret.axis_w.Y(  this.axis_w.X()*rhs.axis_x.Y() +
                       this.axis_w.Y()*rhs.axis_y.Y() +
                       this.axis_w.Z()*rhs.axis_z.Y() +
                       this.pad_ww    *rhs.axis_w.Y());
        ret.axis_w.Z(  this.axis_w.X()*rhs.axis_x.Z() +
                       this.axis_w.Y()*rhs.axis_y.Z() +
                       this.axis_w.Z()*rhs.axis_z.Z() +
                       this.pad_ww    *rhs.axis_w.Z());
        ret.pad_ww =   this.axis_w.X()*rhs.pad_xw     +
                       this.axis_w.Y()*rhs.pad_yw     +
                       this.axis_w.Z()*rhs.pad_zw     +
                       this.pad_ww    *rhs.pad_ww     ;

        return ret;
    }

    public matrix3 DividedBy(matrix3 rhs)
    {

    }

    public matrix3 ModBy(matrix3 rhs)
    {

    }


}
